home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Maclife 157
/
MACLIFE157-2001-09.ISO.7z
/
MACLIFE157-2001-09.ISO
/
Linux
/
MacOS Tools
/
BootX 1.2.2
/
Sources
/
lib
/
MoreInterfaceLib
/
MoreInterfaceLib.c
next >
Wrap
Text File
|
2001-07-23
|
19KB
|
501 lines
/*
File: MoreInterfaceLib.c
Contains: Compatibility shim for routines not in InterfaceLib prior to Mac OS 8.5.
Written by: Quinn
Copyright: Copyright ゥ 1999 by Apple Computer, Inc., all rights reserved.
You may incorporate this Apple sample source code into your program(s) without
restriction. This Apple sample source code has been provided "AS IS" and the
responsibility for its operation is yours. You are not permitted to redistribute
this Apple sample source code as "Apple sample source code" after having made
changes. If you're going to re-distribute the source, we require that you make
it clear in the source that the code was descended from Apple sample source
code, but that you've made changes.
Change History (most recent first):
<4> 20/4/99 Quinn Added Gestalt Value routines.
<3> 16/3/99 Quinn Added MoreUTFindDrive and MoreAddDrive. Also fixed some mixups
about which traps are toolbox traps and which aren't.
<2> 1/3/99 Quinn Added MoreFlushCodeCacheRange. Also some general tidy up.
<1> 25/2/99 Quinn First checked in.
*/
/////////////////////////////////////////////////////////////////
// MoreIsBetter Setup
#include "MoreSetup.h"
/////////////////////////////////////////////////////////////////
// Mac OS Interfaces
#include <CodeFragments.h>
#include <LowMem.h>
#include <Traps.h>
#include <FSM.h>
#include <Gestalt.h>
/////////////////////////////////////////////////////////////////
// Our Prototypes
#include "MoreInterfaceLib.h"
/////////////////////////////////////////////////////////////////
// This file contains implementations of various Mac OS API routines
// that were rolled in to InterfaceLib as of Mac OS 8.5. They are
// in the InterfaceLib stub library as of Universal Interfaces 3.2.
// This code does the magic to decide whether the routine is available
// via InterfaceLib, or whether we have to synthesise our own MixedMode
// glue (or, in some cases, implementation).
// If you use any of the routines in this library, you must either:
//
// a) continue to hard link to InterfaceLib, in which case you won't
// launch on pre-8.5 systems (with a cryptic error message), or
// b) weak link to InterfaceLib, in which case you must check that you're
// on 8.5 or later before calling any of these routine lest
// you die by trying to call nil.
// You can change the definition of the following compiler variable,
// which causes these routine to always use the InterfaceLib variant.
// You'd better make sure they're available, as described above.
#ifndef MORE_MAC_OS_8_5_OR_LATER
#define MORE_MAC_OS_8_5_OR_LATER 0
#endif
// Also, Universal Interfaces 3.2 defines macros for some missing
// low memory accessors. For CFM code, these macros override
// the external procedure definition. So you can no longer
// call the real accessors, even if you do depend on Mac OS 8.5
// or greater. This hack fixes the problem. [Radar ID 2308604]
#undef LMGetUnitTableEntryCount
#undef LMSetUnitTableEntryCount
/////////////////////////////////////////////////////////////////
#if TARGET_RT_MAC_CFM
extern pascal SInt16 MoreLMGetUnitTableEntryCount(void)
{
if (MORE_MAC_OS_8_5_OR_LATER || (LMGetUnitTableEntryCount != (void *) kUnresolvedCFragSymbolAddress)) {
return LMGetUnitTableEntryCount();
} else {
return *((SInt16 *) 0x01d2);
}
}
extern pascal void MoreLMSetUnitTableEntryCount(SInt16 value)
{
if (MORE_MAC_OS_8_5_OR_LATER || (LMSetUnitTableEntryCount != (void *) kUnresolvedCFragSymbolAddress)) {
LMSetUnitTableEntryCount(value);
} else {
*((SInt16 *) 0x01d2) = value;
}
}
#endif
/////////////////////////////////////////////////////////////////
// Mixed Mode ProcInfo Helper
// Bit Numbers
//
// 3 2 1 0
// 10987654321098765432109876543210
// Stack Based Layout
//
// cccc <- calling convention = kPascalStackBased (0), kCStackBased (1), kThinkCStackBased (5)
// ss <- result size
// ss <- stack parameter 1 size
// ss <- stack parameter 2 size
// ss <- stack parameter 3 size
// ss <- stack parameter 4 size
// ss <- stack parameter 5 size
// ss <- stack parameter 6 size
// ss <- stack parameter 7 size
// ss <- stack parameter 8 size
// ss <- stack parameter 9 size
// ss <- stack parameter 10 size
// ss <- stack parameter 11 size
// ss <- stack parameter 12 size
// Register Based Layout
//
// cccc <- calling convention = kRegisterBased (2)
// rrrss <- register result location and size
// rrrss <- register parameter 1 location and size
// rrrss <- register parameter 1 location and size
// rrrss <- register parameter 1 location and size
// rrrss <- register parameter 1 location and size
// Dispatched Stack Based Layout
//
// cccc <- calling convention = kD0DispatchedPascalStackBased (8), kD1DispatchedPascalStackBased (12), kD0DispatchedCStackBased (9), kStackDispatchedPascalStackBased (14)
// ss <- result size
// ss <- selector size
// ss <- stack parameter 1 size
// ss <- stack parameter 2 size
// ss <- stack parameter 3 size
// ss <- stack parameter 4 size
// ss <- stack parameter 5 size
// ss <- stack parameter 6 size
// ss <- stack parameter 7 size
// ss <- stack parameter 8 size
// ss <- stack parameter 9 size
// ss <- stack parameter 10 size
// ss <- stack parameter 11 size
// Special Case Layout
//
// cccc <- calling convention = kSpecialCase (15)
// xxxxxx <- special case selector (see "MixedMode.h")
// Values for "ss":
//
// 00 = kNoByteCode
// 01 = kOneByteCode
// 10 = kTwoByteCode
// 11 = kFourByteCode
// Values for "rrr":
//
//
// 000 = kRegisterD0
// 001 = kRegisterD1
// 010 = kRegisterD2
// 011 = kRegisterD3
// 100 = kRegisterA0
// 101 = kRegisterA1
// 110 = kRegisterA2
// 111 = kRegisterA3
/////////////////////////////////////////////////////////////////
#if TARGET_RT_MAC_CFM
// DriverInstallReserveMem is a bit trickier to implement than the
// previous two routines. Basically we have get the address of the
// _DriverInstall ($A03D) trap and then call it using
// CallOSTrapUniversalProc. There are a number of important things
// to note here:
// a) We can just get the trap address and treat it as a UPP.
// The trap tables are defined to contain UPPs, either pointers
// to real 68K code, or pointers to a routine descriptor (if
// the trap is native or fat).
// b) We must use CallOSTrapUniversalProc, not CallUniversalProc.
// CallOSTrapUniversalProc automatically does a number of things
// that are very critical for call OS traps. See "IM:PowerPC
// System Software", p2-42 for a full description.
// c) When calling OS traps from PPC, it's important to get the
// ProcInfo right. Specifically, all OS traps assume an
// implicit parameter of D1 as the first parameter. After
// that, the parameters should be defined in the order that
// they are declared in the prototype. If you fail to get
// the order right, or to put D1 first, your code will work,
// up until it encounters someone who has patched the OS trap
// with a native or fat patch. Then strange things will happen,
// and you'll spend hours in MacsBug trying to figure it out.
// The trap number and ProcInfo description for DriverInstallReserveMem.
enum {
_DriverInstallReserveMem = 0x0A43D
};
enum {
uppDriverInstallProcInfo = kRegisterBased
| REGISTER_RESULT_LOCATION(kRegisterD0)
| RESULT_SIZE(SIZE_CODE(sizeof(OSErr)))
| REGISTER_ROUTINE_PARAMETER(1, kRegisterD1, SIZE_CODE(sizeof(long)))
| REGISTER_ROUTINE_PARAMETER(2, kRegisterA0, SIZE_CODE(sizeof(DRVRHeaderPtr)))
| REGISTER_ROUTINE_PARAMETER(3, kRegisterD0, SIZE_CODE(sizeof(short)))
};
// IMPORTANT: Previous versions of TradDriverLoaderLib defined parameter 1
// as sizeof(short), not sizeof(long). I fixed this based on information
// I extracted from the official Apple version of this glue, in the
// InterfaceLib implementation on Mac OS 8.5.
extern pascal OSErr MoreDriverInstallReserveMem(DRVRHeaderPtr drvrPtr, DriverRefNum refNum)
{
if (MORE_MAC_OS_8_5_OR_LATER || (DriverInstallReserveMem != (void *) kUnresolvedCFragSymbolAddress)) {
return DriverInstallReserveMem(drvrPtr, refNum);
} else {
UniversalProcPtr trapAddress;
// Check that I've got the ProcInfo correct. This magic value
// was extracted from InterfaceLib on Mac OS 8.5.
MoreAssert(uppDriverInstallProcInfo == 0x00533822);
trapAddress = GetOSTrapAddress(_DriverInstallReserveMem);
return CallOSTrapUniversalProc(trapAddress, uppDriverInstallProcInfo, _DriverInstallReserveMem, drvrPtr, refNum);
}
}
#endif
/////////////////////////////////////////////////////////////////
#if TARGET_RT_MAC_CFM
enum {
uppFlushCodeCacheRangeProcInfo = kRegisterBased |
RESULT_SIZE(SIZE_CODE(sizeof(OSErr))) |
REGISTER_RESULT_LOCATION(kRegisterD0) |
REGISTER_ROUTINE_PARAMETER(1, kRegisterD0, SIZE_CODE(sizeof(long))) |
REGISTER_ROUTINE_PARAMETER(2, kRegisterD1, SIZE_CODE(sizeof(long))) |
REGISTER_ROUTINE_PARAMETER(3, kRegisterA0, SIZE_CODE(sizeof(void *))) |
REGISTER_ROUTINE_PARAMETER(4, kRegisterA1, SIZE_CODE(sizeof(unsigned long)))
};
extern pascal OSErr MoreFlushCodeCacheRange(void *address, unsigned long count)
{
if (MORE_MAC_OS_8_5_OR_LATER || (FlushCodeCacheRange != (void *) kUnresolvedCFragSymbolAddress)) {
return FlushCodeCacheRange(address, count);
} else {
UniversalProcPtr trapAddress;
// Check that I've got the ProcInfo correct. This magic value
// was extracted from InterfaceLib on Mac OS 8.5.
MoreAssert(uppFlushCodeCacheRangeProcInfo == 0x5e671822);
trapAddress = GetOSTrapAddress(_HWPriv);
return CallOSTrapUniversalProc(trapAddress, uppFlushCodeCacheRangeProcInfo, 9, _HWPriv, address, count);
}
}
#endif
/////////////////////////////////////////////////////////////////
#if TARGET_RT_MAC_CFM
enum {
uppUTFindDriveProcInfo = kD0DispatchedPascalStackBased |
RESULT_SIZE(SIZE_CODE(sizeof(OSErr))) |
DISPATCHED_STACK_ROUTINE_SELECTOR_SIZE(SIZE_CODE(sizeof(long))) |
DISPATCHED_STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(SInt16))) |
DISPATCHED_STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(DrvQElPtr *)))
};
extern pascal OSErr MoreUTFindDrive(SInt16 driveNum, DrvQElPtr *driveQElementPtr)
{
if (MORE_MAC_OS_8_5_OR_LATER || (UTFindDrive != (void *) kUnresolvedCFragSymbolAddress)) {
return UTFindDrive(driveNum, driveQElementPtr);
} else {
UniversalProcPtr trapAddress;
// Check that I've got the ProcInfo correct. This magic value
// was extracted from InterfaceLib on Mac OS 8.5.
MoreAssert(uppUTFindDriveProcInfo == 0x0EE8);
trapAddress = GetToolboxTrapAddress(_HFSUtilDispatch);
return CallUniversalProc(trapAddress, uppUTFindDriveProcInfo, 15, driveNum, driveQElementPtr);
}
}
#endif
/////////////////////////////////////////////////////////////////
#if TARGET_RT_MAC_CFM
enum {
uppAddDriveProcInfo = kRegisterBased |
RESULT_SIZE(SIZE_CODE(sizeof(OSErr))) |
REGISTER_RESULT_LOCATION(kRegisterD0) |
REGISTER_ROUTINE_PARAMETER(1, kRegisterD1, SIZE_CODE(sizeof(short))) |
REGISTER_ROUTINE_PARAMETER(2, kRegisterA0, SIZE_CODE(sizeof(DrvQElPtr))) |
REGISTER_ROUTINE_PARAMETER(3, kRegisterD0, SIZE_CODE(sizeof(long)))
};
// Some comments about the ProcInfo value:
//
// o It's set to return a result even though the high-level glue doesn't.
// This is because the trap returns a result in D0. We can safely ignored
// it from the C code.
//
// o The D1 parameter is listed as sizeof(short), not sizeof(long) which is
// the size used by most other OS traps. The reason: I'm not sure.
// Come to think of it, sizeof(short) makes more sense to me because
// that's what trap words are. Anyway, I'm just parroting what
// InterfaceLib 8.5 does; my specific goal is to make CFM patches to
// AddDrive work properly, which requires that we all use identical
// ProcInfo's.
//
// o Register D0 contains the drvrRefNum and drvNum parameters combined,
// with drvNum in the high word and drvrRefNum in the low word.
// Oh, those wacky 68K calling conventions (-:
extern pascal void MoreAddDrive(DriverRefNum drvrRefNum, SInt16 drvNum, DrvQElPtr qEl)
{
UInt32 response;
if ( MORE_MAC_OS_8_5_OR_LATER || ((Gestalt(gestaltSystemVersion, (SInt32 *) &response) == noErr) && (response >= 0x0850))) {
AddDrive(drvrRefNum, drvNum, qEl);
} else {
UniversalProcPtr trapAddress;
// Prior to Mac OS 8.5, the InterfaceLib glue for AddDrive was
// messed up, so we have to roll our own.
// Check that I've got the ProcInfo correct. This magic value
// was extracted from InterfaceLib on Mac OS 8.5.
MoreAssert(uppAddDriveProcInfo == 0x0733022);
trapAddress = GetOSTrapAddress(_AddDrive);
(void) CallOSTrapUniversalProc(trapAddress, uppUTFindDriveProcInfo, _AddDrive, qEl, ( ((UInt32) drvNum) << 16) | (UInt16) drvrRefNum);
}
}
#else
// Unlike most of these glue routines, the 68K version of AddDrive
// is implemented as link-in glue. Thus there are no inlines in the
// interface file. We therefore have to implement this routine for
// classic 68K, as a simple call through to the real routine.
extern pascal void MoreAddDrive(DriverRefNum drvrRefNum, SInt16 drvNum, DrvQElPtr qEl)
{
AddDrive(drvrRefNum, drvNum, qEl);
}
#endif
/////////////////////////////////////////////////////////////////
#if TARGET_RT_MAC_CFM
enum {
_GestaltValue = 0xABF1
};
enum {
uppNewGestaltValueProcInfo = kD0DispatchedPascalStackBased |
RESULT_SIZE(SIZE_CODE(sizeof(OSErr))) |
DISPATCHED_STACK_ROUTINE_SELECTOR_SIZE(SIZE_CODE(sizeof(short))) |
DISPATCHED_STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(OSType))) |
DISPATCHED_STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(long))),
uppReplaceGestaltValueProcInfo = kD0DispatchedPascalStackBased |
RESULT_SIZE(SIZE_CODE(sizeof(OSErr))) |
DISPATCHED_STACK_ROUTINE_SELECTOR_SIZE(SIZE_CODE(sizeof(short))) |
DISPATCHED_STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(OSType))) |
DISPATCHED_STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(long))),
uppSetGestaltValueProcInfo = kD0DispatchedPascalStackBased |
RESULT_SIZE(SIZE_CODE(sizeof(OSErr))) |
DISPATCHED_STACK_ROUTINE_SELECTOR_SIZE(SIZE_CODE(sizeof(short))) |
DISPATCHED_STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(OSType))) |
DISPATCHED_STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(long))),
uppDeleteGestaltValueProcInfo = kD0DispatchedPascalStackBased |
RESULT_SIZE(SIZE_CODE(sizeof(OSErr))) |
DISPATCHED_STACK_ROUTINE_SELECTOR_SIZE(SIZE_CODE(sizeof(short))) |
DISPATCHED_STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(OSType)))
};
// The glue I use here is especially cheesy. In general, I try
// to avoid using the pre-processor for generating bogus C syntax,
// ie I only use #if where I could syntactically use if(). However,
// in this case I've been forced to break my own rules. The problem
// is that NewGestaltValue etc are not present in Universal Interface's
// 3.2 InterfaceLib for CFM-68K. Why? I don't know for sure, but it
// could be because they are only available in the real InterfaceLib for
// Mac OS 8.5 and higher, and that can't be run on 68K machines. Anyway,
// given that they're not available in InterfaceLib, you can't reference
// the symbol in the CFM-68K build, which requires ugly preprocessor
// stuff. There may be a better way of doing this, but I'm pushed for
// time right now. I hope to revisit it eventually.
// -- Quinn, 20 Apr 1999
extern pascal OSErr MoreNewGestaltValue(OSType selector, long newValue)
{
#if !TARGET_CPU_68K
if (MORE_MAC_OS_8_5_OR_LATER || (NewGestaltValue != (void *) kUnresolvedCFragSymbolAddress)) {
return NewGestaltValue(selector, newValue);
} else
#endif
{
UniversalProcPtr trapAddress;
// Check that I've got the ProcInfo correct. This magic value
// was extracted from InterfaceLib on Mac OS 8.5.
MoreAssert(uppNewGestaltValueProcInfo == 0x00000FA8);
trapAddress = GetToolboxTrapAddress(_GestaltValue);
return CallUniversalProc(trapAddress, uppNewGestaltValueProcInfo, selector, newValue);
}
}
extern pascal OSErr MoreReplaceGestaltValue(OSType selector, long replacementValue)
{
#if !TARGET_CPU_68K
if (MORE_MAC_OS_8_5_OR_LATER || (ReplaceGestaltValue != (void *) kUnresolvedCFragSymbolAddress)) {
return ReplaceGestaltValue(selector, replacementValue);
} else
#endif
{
UniversalProcPtr trapAddress;
// Check that I've got the ProcInfo correct. This magic value
// was extracted from InterfaceLib on Mac OS 8.5.
MoreAssert(uppReplaceGestaltValueProcInfo == 0x00000FA8);
trapAddress = GetToolboxTrapAddress(_GestaltValue);
return CallUniversalProc(trapAddress, uppReplaceGestaltValueProcInfo, selector, replacementValue);
}
}
extern pascal OSErr MoreSetGestaltValue(OSType selector, long newValue)
{
#if !TARGET_CPU_68K
if (MORE_MAC_OS_8_5_OR_LATER || (SetGestaltValue != (void *) kUnresolvedCFragSymbolAddress)) {
return SetGestaltValue(selector, newValue);
} else
#endif
{
UniversalProcPtr trapAddress;
// Check that I've got the ProcInfo correct. This magic value
// was extracted from InterfaceLib on Mac OS 8.5.
MoreAssert(uppSetGestaltValueProcInfo == 0x00000FA8);
trapAddress = GetToolboxTrapAddress(_GestaltValue);
return CallUniversalProc(trapAddress, uppSetGestaltValueProcInfo, selector, newValue);
}
}
extern pascal OSErr MoreDeleteGestaltValue(OSType selector)
{
#if !TARGET_CPU_68K
if (MORE_MAC_OS_8_5_OR_LATER || (DeleteGestaltValue != (void *) kUnresolvedCFragSymbolAddress)) {
return DeleteGestaltValue(selector);
} else
#endif
{
UniversalProcPtr trapAddress;
// Check that I've got the ProcInfo correct. This magic value
// was extracted from InterfaceLib on Mac OS 8.5.
MoreAssert(uppDeleteGestaltValueProcInfo == 0x000003A8);
trapAddress = GetToolboxTrapAddress(_GestaltValue);
return CallUniversalProc(trapAddress, uppDeleteGestaltValueProcInfo, selector);
}
}
#endif